﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Input;

namespace Project_1_refactored_
{
    
    //possible states for player
    enum PlayerStates
    {
        Idle,
        Run,
        Jump,
        Attack,
        Die

    }

    partial class Player : GameObject
    {
        #region Declarations
        //inherits: v2Position, t2dTexture for now
        const string Player_idle = @"Character\knight96x96\idle";
        const string Player_run = @"Character\knight96x96\run";
        const string Player_jump = @"Character\knight96x96\jump";
        const string Player_attack = @"Character\knight96x96\attack";
        const string Player_die = @"Character\knight96x96\die";
        const int Player_Speed = 160;

        const float Move_UP = -1.5f;
        const float Move_DOWN = 1.5f;
        const float Move_LEFT = -1.5f;
        const float Move_RIGHT = 1.5f;

        PlayerStates playerCurrentState = PlayerStates.Idle;
        public PlayerStates pSTATE { get { return playerCurrentState; } }

        Vector2 pDirection = Vector2.Zero;
        Vector2 pSpeed = Vector2.Zero;

        KeyboardState previousKeyboardState;

        Vector2 startingPosition = Vector2.Zero;

        //WEAPONRY
        List<Weapon> pWeapon = new List<Weapon>();
        public List<Weapon> pWeapons
        {
            get { return pWeapon; }
        }
        //WEAPONRY
        ContentManager pContentMng;
    #endregion
        
        #region LoadContent
        public void LoadContent(ContentManager Content)
        {
            //WEAPONRY
            pContentMng = Content;
            //WEAPONRY
            foreach (Weapon weapon in pWeapon)
                weapon.LoadContent(pContentMng);
            Animated = true; // making sure it will animate
            frameWidth = 96;
            base.LoadContent(Content, Player_idle, Player_run, Player_jump, Player_attack, Player_die, new int[]{12,12,12,12,11});
            v2Position.Y -= t2dIdle.Height; //makes them at the bottom of the screen
            frameHeight = t2dIdle.Height; // frame height assignment

            //CHARACTERISTICS INITIALIZATION
            base.newPlayer("TESTER");
            base.LoadHPContent(Content); //HP MINI BAR
        }
        #endregion

        #region updateMethods
        public void Update(GameTime gameTime)
        {
            //we r keeping a track of asset name in order to know the amount of frames based on assetName
            string asset = "";
            switch (playerCurrentState)
            {
                case PlayerStates.Idle:
                    asset = "Idle";
                    break;
                case PlayerStates.Run:
                    asset = "Run";
                    break;
                case PlayerStates.Jump:
                    asset = "Jump";
                    break;
                case PlayerStates.Attack:
                    asset = "Attack";
                    break;
                case PlayerStates.Die:
                    asset = "Die";
                    break;
            }

            //CHECK FOR DYING BEGIN
            if (playerCurrentState == PlayerStates.Die)
            {
                base.dying = true;
            }
            //CHECK FOR DYING END

            KeyboardState kcurrentState = Keyboard.GetState();
            UpdateMovement(kcurrentState);
            UpdateJump(kcurrentState);
            UpdateWeapon(gameTime, kcurrentState);
            previousKeyboardState = kcurrentState;

            //handles reaching X boundaries
            collisionHandler();

            base.HPInfoUpdate(v2Position); //HP MINI BAR
            base.Update(gameTime, asset);
            base.Update(gameTime, pSpeed, pDirection);
        }

        #region movement update
        private void UpdateMovement(KeyboardState currentKeyboardState)
        {
            if (playerCurrentState == PlayerStates.Idle || playerCurrentState == PlayerStates.Run)
            {
                pSpeed = Vector2.Zero;
                pDirection = Vector2.Zero;

                if (currentKeyboardState.IsKeyDown(Keys.Left))
                {
                        frameRate = 0.05f;
                        playerCurrentState = PlayerStates.Run;
                        pSpeed.X = Player_Speed;
                        pDirection.X = Move_LEFT;
                        faceLeft = true;
                }
                else if (currentKeyboardState.IsKeyDown(Keys.Right))
                {
                        frameRate = 0.05f;
                        playerCurrentState = PlayerStates.Run;
                        pSpeed.X = Player_Speed;
                        pDirection.X = Move_RIGHT;
                        faceLeft = false;
                }
                else
                {
                    frameRate = 0.10f;
                    playerCurrentState = PlayerStates.Idle;
                    faceLeft = false;
                }
            }
        }

        private void UpdateJump(KeyboardState currentKeyboardState)
        {
            if (playerCurrentState == PlayerStates.Idle || playerCurrentState == PlayerStates.Run)
                if (currentKeyboardState.IsKeyDown(Keys.Space) && !previousKeyboardState.IsKeyDown(Keys.Space))
                    Jump(); //frameRate = 0.2f;

            if (playerCurrentState == PlayerStates.Jump)
            {
                if (startingPosition.Y - v2Position.Y > 100)
                    pDirection.Y = Move_DOWN;
                if (v2Position.Y > startingPosition.Y)
                {
                    v2Position.Y = startingPosition.Y;
                    playerCurrentState = PlayerStates.Idle;
                    pDirection = Vector2.Zero;
                }
            }
        }

        private void Jump()
        {
            if (playerCurrentState != PlayerStates.Jump)
            {
                playerCurrentState = PlayerStates.Jump;
                startingPosition = v2Position;
                pDirection.Y = Move_UP;
                pSpeed = new Vector2(Player_Speed, Player_Speed);
            }
        }
        #endregion

        #region Weapons update
        private void UpdateWeapon(GameTime gameTime, KeyboardState currentKeyboardState)
        {
            foreach (Weapon weapon in pWeapon)
                weapon.Update(gameTime);

            if (currentKeyboardState.IsKeyDown(Keys.A) && !previousKeyboardState.IsKeyDown(Keys.A))
                throwWeapon();
        }

        private void throwWeapon()
        {
            if (playerCurrentState == PlayerStates.Idle || playerCurrentState == PlayerStates.Jump || playerCurrentState == PlayerStates.Run)
            {
                bool aCreateNew = true;
                //when the dagger reaches his MAX_END he becames inActive, we dont delete him, thats the first if statement
                foreach (Weapon weapon in pWeapon)
                {
                    if (weapon.WeaponState == weaponStates.inActive)
                    {
                        aCreateNew = false;
                        weapon.throwDagger(v2Position + new Vector2(frameWidth / 2, frameHeight / 2), new Vector2(200, 0), new Vector2(1, 0));
                        break;
                    }
                }

                if (aCreateNew == true)
                {
                    Weapon aWeapon = new Weapon();
                    aWeapon.LoadContent(pContentMng);
                    aWeapon.throwDagger(v2Position + new Vector2(frameWidth / 2, frameHeight / 2), new Vector2(200, 0), new Vector2(1, 0));
                    pWeapon.Add(aWeapon);
                }
            }
        }
#endregion

        #endregion

        #region Draw method

        public new void Draw(SpriteBatch spriteBatch)
        {
            foreach (Weapon weapon in pWeapon)
                weapon.Draw(spriteBatch);

            SpriteEffects effect = SpriteEffects.None;
            if (Animated)
            {
                if (faceLeft == true)
                    effect = SpriteEffects.FlipHorizontally;

                base.DrawHPandTEXT(spriteBatch);
                //REFACTORED FROM IF TO SWITCH
                switch (playerCurrentState)
                {
                    case PlayerStates.Idle:
                        spriteBatch.Draw(t2dIdle, new Rectangle((int)v2Position.X, (int)v2Position.Y, frameWidth, frameHeight), getSourceRect(), Color.White);
                        break;
                    case PlayerStates.Run:
                        spriteBatch.Draw(t2dRun, new Rectangle((int)v2Position.X, (int)v2Position.Y, frameWidth, frameHeight), getSourceRect(), Color.White, 0f, Vector2.Zero, effect, 0f);
                        break;
                    case PlayerStates.Jump:
                        spriteBatch.Draw(t2dJump, new Rectangle((int)v2Position.X, (int)v2Position.Y, frameWidth, frameHeight), getSourceRect(), Color.White, 0f, Vector2.Zero, effect, 0f);
                        break;
                    case PlayerStates.Attack:
                        spriteBatch.Draw(t2dAttack, new Rectangle((int)v2Position.X, (int)v2Position.Y, frameWidth, frameHeight), getSourceRect(), Color.White, 0f, Vector2.Zero, effect, 0f);
                        break;
                    case PlayerStates.Die:
                        spriteBatch.Draw(t2dDie, new Rectangle((int)v2Position.X, (int)v2Position.Y, frameWidth, frameHeight), getSourceRect(), Color.White);
                        break;
                }
            }
        }
        #endregion

        #region public methods
        public void removeWeapon(Weapon weapon)
        {
            pWeapon[pWeapons.IndexOf(weapon)].deActivate();
        }

        //very easy collision handler
        public void collisionHandler()
        {
            if (v2Position.X < 0)
                pDirection.X = Move_RIGHT;
            if (v2Position.X > worldWidth - frameWidth)
                pDirection.X = Move_LEFT;
        }
        #endregion

        #region helper methods
        public void applyRangeDmg()
        {
            checkAlive();
            if (HP >= RANGE_ATTACK)
                HP -= RANGE_ATTACK;
        }

        public void applyMeleeDmg()
        {
            checkAlive();
            if (HP >= MELEE_ATTACK)
                HP -= MELEE_ATTACK;
        }

        public void checkAlive()
        {
            if (HP <= 0)
                playerCurrentState = PlayerStates.Die;
        }
        #endregion
    }
}
